#include <kew/c-vm.h>
#include <kew/stdlib.h>

/* FIXME: this dynamic variable implementation does not attach the variable as an extension of the env
 * and therefore will not work correctly if we get to the stage of supporting multiple threads */
 
KewDynamicVariableObject *kew_check_dynamic_variable(KewDynamicEnvironment *env, KewStaticEnvironment *security_context, KewObject *object)
{
    return (KewDynamicVariableObject *) kew_check_type(env, security_context, object, "dynamic variable", kew_sel_dynamicVariable);
}

void kew_dynamic_variable_push(KewDynamicEnvironment *env, KewDynamicVariableObject *dynvar, KewObject *value)
{
    dynvar->value_stack = g_slist_prepend(dynvar->value_stack, value);
}

void kew_dynamic_variable_pop(KewDynamicEnvironment *env, KewDynamicVariableObject *dynvar)
{
    GSList *junk = dynvar->value_stack;
    dynvar->value_stack = g_slist_next(dynvar->value_stack);
    g_free(junk);
}

KEW_EXPORT_METHOD(kew_action_set_dynamic_variable)
{
    KewDynamicVariableObject *dynvar = kew_check_dynamic_variable(env, NULL, args[0]);
    
    kew_dynamic_variable_push(env, dynvar, args[1]);
    
    KEW_ENSURED_FRAME_BEGIN(env, kew_dynamic_variable_pop, dynvar);

    kew_send_full(env, receiver, kew_sel_call, KEW_CALL_SHAPE_00, NULL, NULL);

    KEW_ENSURED_FRAME_END(env);
}

KEW_EXPORT_METHOD(kew_dynamic_variable_read)
{
    results[0] = (KewObject *) (((KewDynamicVariableObject *) receiver)->value_stack->data);
}
